package com.siteseat.common.security;

import java.util.HashMap;
import java.util.Map;

import com.siteseat.common.exception.InternalException;

/**
 *
 */
public class Permission {

  public static final Permission CREDENTIAL_ADD = new Permission( 1, "CREDENTIAL_ADD" );
  public static final Permission CREDENTIAL_CHANGE_PASSWORD = new Permission( 2, "CREDENTIAL_CHANGE_PASSWORD" );
  public static final Permission CREDENTIAL_REMOVE = new Permission( 3, "CREDENTIAL_REMOVE" );

  public static final Permission ADMINISTRATOR_ADD = new Permission( 1001, "ADMINISTRATOR_ADD" );
  public static final Permission ADMINISTRATOR_CHANGE_PASSWORD = new Permission( 1002, "ADMINISTRATOR_CHANGE_PASSWORD" );
  public static final Permission ADMINISTRATOR_REMOVE = new Permission( 1003, "ADMINISTRATOR_REMOVE" );

  public static final Permission PERMISSION_GRANT = new Permission( 2001, "PERMISSION_GRANT" );
  public static final Permission PERMISSION_REVOKE = new Permission( 2002, "PERMISSION_REVOKE" );
  
  public static final Map<Integer,Permission> BY_CODE = new HashMap<Integer,Permission>();
  
  public static final Map<String,Permission> BY_NAME = new HashMap<String,Permission>();
  
  static {
    registerPermission( CREDENTIAL_ADD );
    registerPermission( CREDENTIAL_CHANGE_PASSWORD );
    registerPermission( CREDENTIAL_REMOVE );

    registerPermission( ADMINISTRATOR_ADD );
    registerPermission( ADMINISTRATOR_CHANGE_PASSWORD );
    registerPermission( ADMINISTRATOR_REMOVE );

    registerPermission( PERMISSION_GRANT );
    registerPermission( PERMISSION_REVOKE );
  }
  
  /**
   * 
   *
   * @param p
   */
  public static synchronized void registerPermission( Permission p ) {
    if( BY_CODE.containsKey( p.code ) ) {
      Permission old = BY_CODE.get( p.code );
      throw new InternalException( "Duplicated code " + p.code + " between " + p.name + " and " + old.name );
    }
    if( BY_NAME.containsKey( p.name ) ) {
      Permission old = BY_NAME.get( p.name );
      throw new InternalException( "Duplicated name " + p.name + " between " + p.code + " and " + old.code );
    }
    BY_CODE.put( p.code, p );
    BY_NAME.put( p.name, p );
  }
  
  /**
   * 
   *
   * @param code
   * @return
   */
  public static synchronized Permission forCode( Integer code ) {
    return BY_CODE.get( code );
  }
  
  /**
   * 
   *
   * @param name
   * @return
   */
  public static synchronized Permission forName( String name ) {
    return BY_NAME.get( name );
  }


  private String name;
  private Integer code;
  
  /**
   * Ctor
   *
   *
   * @param code
   * @param name
   */
  public Permission( int code, String name ) {
    this.code = Integer.valueOf(code);
    this.name = name;
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return this.name;
  }

  /**
   * Gets the name
   *
   * @return the name
   */
  public String getName() {
    return name;
  }

  /**
   * Gets the code
   *
   * @return the code
   */
  public Integer getCode() {
    return code;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean equals( Object obj ) {
    return this.code.intValue() == ((Permission)obj).code.intValue();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int hashCode() {
    return this.code.intValue();
  }

  
}
